package kr.zetaomicron.ultrasolitaire;

import java.util.ArrayList;
import java.util.List;

import javax.microedition.khronos.opengles.GL10;

import android.util.Log;

//import kr.zetaomicron.ultrasolitaire.MainMenuScreen.MainMenuMode;
import kr.zetaomicron.ultrasolitaire.World.WorldListener;
import kr.zetaomicron.framework.Game;
import kr.zetaomicron.framework.Input.TouchEvent;
import kr.zetaomicron.framework.gl.Camera2D;
import kr.zetaomicron.framework.gl.FPSCounter;
import kr.zetaomicron.framework.gl.SpriteBatcher;
import kr.zetaomicron.framework.gl.TextureRegion;
import kr.zetaomicron.framework.impl.GLScreen;
import kr.zetaomicron.framework.math.OverlapTester;
import kr.zetaomicron.framework.math.Rectangle;
import kr.zetaomicron.framework.math.Vector2;

public class GameScreen extends GLScreen {
    static final int GAME_EXECUTE = -2, GAME_SETTINGS = -1, GAME_READY = 0, GAME_RUNNING = 1;
    static final int GAME_LEVEL_END = 3, GAME_OVER = 4;
  
    int state;
    Camera2D guiCam;
    Vector2 touchPoint, touchDownPoint, touchDownPoint_delta;
    SpriteBatcher batcher;    
    World world;
    WorldListener worldListener;
    WorldRenderer renderer;
    GameSettings gameset;
    Rectangle rect_btnZIn, rect_btnZOut, rect_btnAutoplay, rect_btnUndo, rect_btnRedo;
    Rectangle rect_colscrollLeftFound, rect_colscrollRightFound, rect_colscrollLeftTab, rect_colscrollRightTab;
    Rectangle quitBounds;
    Rectangle rect_btnOK, rect_btnCancel;
    List<Rectangle> list_rect_settings;
    int lastScore;
    int[] lastGameSettings;	// not to update when gamesetting mode: suits, decks, ranks, deal
    String scoreString;
    float tmpOpenReady = 1.0f;

    public GameScreen(Game game) {
        super(game);
        state = GAME_EXECUTE;
        guiCam = new Camera2D(glGraphics, Settings.WORLD_WIDTH, Settings.WORLD_HEIGHT);
        touchPoint = new Vector2();	touchDownPoint = new Vector2();
        touchDownPoint_delta = new Vector2();
        batcher = new SpriteBatcher(glGraphics, 1000);
        worldListener = new WorldListener() {
        };
        world = new World(worldListener);
        renderer = new WorldRenderer(glGraphics, batcher, world);
        
        gameset = new GameSettings(Settings.WORLD_WIDTH / 2, Settings.WORLD_HEIGHT / 2);
        rect_btnOK = gameset.getRectBtnOk();
        rect_btnCancel = gameset.getRectBtnCancel();
        rect_btnZIn = new Rectangle(10, Settings.WORLD_HEIGHT - 105, 60, 105);
       	rect_btnZOut = new Rectangle(10, Settings.WORLD_HEIGHT - 105 * 2, 60, 105);
       	rect_btnAutoplay = new Rectangle(10, 105 * 2, 60, 105);
       	rect_btnUndo = new Rectangle(10, 105, 60, 105);
       	rect_btnRedo = new Rectangle(10, 0, 60, 105);
       	list_rect_settings = new ArrayList<Rectangle>();
       	for (int i = 0; i < 3; ++i) {	list_rect_settings.add(gameset.getRectIcons(0, i));	}
       	for (int i = 0; i < 4; ++i) {	list_rect_settings.add(gameset.getRectIcons(1, i));	}
       	for (int i = 0; i < 3; ++i) {	list_rect_settings.add(gameset.getRectIcons(2, i));	}
       	for (int i = 0; i < 2; ++i) {	list_rect_settings.add(gameset.getRectIcons(3, i));	}

       	float tmpScrollX = 100, tmpScrollWidth = Settings.WORLD_WIDTH - Card.WIDTH - 100;
       	rect_colscrollLeftTab = new Rectangle(100, Settings.WORLD_HEIGHT - 40, tmpScrollWidth, 40);
       	rect_colscrollRightTab = new Rectangle(100, 0, tmpScrollWidth, 40);
    	tmpScrollX = Settings.WORLD_WIDTH - (10 + Card.WIDTH);	tmpScrollWidth = Card.WIDTH + 10;
       	rect_colscrollLeftFound = new Rectangle(tmpScrollX, Settings.WORLD_HEIGHT - 40, tmpScrollWidth, 40);
       	rect_colscrollRightFound = new Rectangle(tmpScrollX, 0, tmpScrollWidth, 40);
        quitBounds = new Rectangle(160 - 96, 240 - 36, 192, 36);

        lastScore = 0;
        lastGameSettings = new int[] {0, 0, 0, 0};
        scoreString = "score: 0";
    }

    @Override
    public void update(float deltaTime) {
        if (deltaTime > 0.1f)	deltaTime = 0.1f;
        
        switch(state) {
        case GAME_EXECUTE:	updateExecute(deltaTime);	break;
        case GAME_SETTINGS:	updateSettings();	break;
        case GAME_RUNNING:	updateRunning(deltaTime);	break;
        case GAME_LEVEL_END:	updateLevelEnd();	break;
        case GAME_OVER:	updateGameOver();	break;
        }
    }
    
    private void updateExecute(float deltaTime) {
    	if (Settings.tmpGameSettings)	state = GAME_SETTINGS;
//    	if (game.getInput().getTouchEvents().size() > 0) {
//            state = GAME_OPENREADY;
//        }
//    	if (deltaTime > 0.0f) {
//    		tmpOpenReady -= deltaTime;
//    		if (tmpOpenReady < 0.0f) {
//    			tmpOpenReady = 0.0f;	state = GAME_READY;
//    		}
//    	}
    }

    private void updateSettings() {
    	List<TouchEvent> touchEvents = game.getInput().getTouchEvents();
    	int len = touchEvents.size();
    	
    	for(int i = 0; i < len; i++) {
    		TouchEvent event = touchEvents.get(i);
    		if (event.type == TouchEvent.TOUCH_UP) {
    			touchPoint.set(event.x, event.y);
                guiCam.touchToWorld(touchPoint);
    	    	//Log.i("[GameScreen]", "[updateSettings] touchup");
		    	if (OverlapTester.pointInRectangle(rect_btnOK, touchPoint)) {
		            //Assets.playSound(Assets.clickSound);
		    		Settings.tmpGameSettings = false;
		    		// this setting is updated now
		    		for (int settingsIdx = 0; settingsIdx <= 3; ++settingsIdx) {
		    			Settings.gameSettings[settingsIdx] = lastGameSettings[settingsIdx];
		    		}
		        	world.InitGame(Rules.KLONDIKE, batcher);
		        	state = GAME_RUNNING;	Settings.gameRunning = true;
		        	return;
		        }
		    	if (OverlapTester.pointInRectangle(rect_btnCancel, touchPoint)) {
		    		Settings.tmpGameSettings = false;
		    		// reset
		    		for (int settingsIdx = 0; settingsIdx <= 3; ++settingsIdx) {
		    			lastGameSettings[settingsIdx] = Settings.gameSettings[settingsIdx];
		    		}

    				switch (lastGameSettings[0]) {
    				default:	Settings.gameSettings_max[1] = 3;	break;
    				case 1:	Settings.gameSettings_max[1] = 2;	break;
    				case 2:	Settings.gameSettings_max[1] = 1;	break;
    				}

		    		if (Settings.gameRunning)	state = GAME_RUNNING;	// continues game
		    		else	state = GAME_EXECUTE;
		    		return;
		    	}
		    	for (int j = 0; j < 3; ++j) {
		    		if (OverlapTester.pointInRectangle(list_rect_settings.get(j), touchPoint)) {
		    			if (j <= Settings.gameSettings_max[0]) {
		    				lastGameSettings[0] = j;
		    				switch (j) {
		    				default:	Settings.gameSettings_max[1] = 3;	break;
		    				case 1:	Settings.gameSettings_max[1] = 2;	break;
		    				case 2:	Settings.gameSettings_max[1] = 1;	break;
		    				}
		    				if (Settings.gameSettings_max[1] < lastGameSettings[1]) {
		    					lastGameSettings[1] = Settings.gameSettings_max[1];
		    				}
		    			}
			    		return;
			    	}
		    	}
		    	for (int j = 0; j < 4; ++j) {
		    		if (OverlapTester.pointInRectangle(list_rect_settings.get(3 + j), touchPoint)) {
		    			if (j <= Settings.gameSettings_max[1])	lastGameSettings[1] = j;
			    		return;
			    	}
		    	}
		    	for (int j = 0; j < 3; ++j) {
		    		if (OverlapTester.pointInRectangle(list_rect_settings.get(7 + j), touchPoint)) {
			    		//if (j <= Settings.gameSettings_max[2])	Settings.gameSettings[2] = j;
		    			if (j <= Settings.gameSettings_max[2])	lastGameSettings[2] = j;
			    		return;
			    	}
		    	}
		    	for (int j = 0; j < 2; ++j) {
		    		if (OverlapTester.pointInRectangle(list_rect_settings.get(10 + j), touchPoint)) {
		    			if (j <= Settings.gameSettings_max[3])	lastGameSettings[3] = j;
			    		return;
			    	}
		    	}
    		}
    	}
    }

    private void updateRunning(float deltaTime) {
    	if (Settings.tmpGameSettings) {	state = GAME_SETTINGS;	return;	}
    	
    	// Scrolls columns
    	int SUITS = 4 + 2 * Settings.gameSettings[0], DECKS = 1 + Settings.gameSettings[1];
    	int NUM_FOUNDS = SUITS * DECKS, FIRST_TABLEAU = 2 + NUM_FOUNDS;
    	CardAnchor anchorFirstFound = world.GetCardAnchors()[0];
    	CardAnchor anchorFirstTab = world.GetCardAnchors()[FIRST_TABLEAU];
    	float leftAnchorY = Settings.WORLD_HEIGHT - Settings.BTN_SCROLL_WIDTH
    			- (Settings.WORLD_HEIGHT - Settings.BTN_SCROLL_WIDTH * 2) / (Settings.columnNum * 2);
    	float anchorHeight = (Settings.WORLD_HEIGHT - Settings.BTN_SCROLL_WIDTH * 2) / Settings.columnNum;
    	if (anchorFirstFound.GetY() < leftAnchorY + anchorHeight * Settings.columnIndices[1]) {
    		world.GetRules().Scroll(false, deltaTime * 500);	Settings.columnIndices[2] = -1;	// moving left
    		if (anchorFirstFound.GetY() > leftAnchorY + anchorHeight * Settings.columnIndices[1]) {
    			world.GetRules().ScrollImmed(false, leftAnchorY + anchorHeight * Settings.columnIndices[1]);
    		}
    	} else if (anchorFirstFound.GetY() > leftAnchorY + anchorHeight * Settings.columnIndices[1]) {
    		world.GetRules().Scroll(false, -deltaTime * 500);	Settings.columnIndices[2] = 1;	// moving right
    		if (anchorFirstFound.GetY() < leftAnchorY + anchorHeight * Settings.columnIndices[1]) {
    			world.GetRules().ScrollImmed(false, leftAnchorY + anchorHeight * Settings.columnIndices[1]);
    		}
    	}
    	if (anchorFirstTab.GetY() < leftAnchorY + anchorHeight * Settings.columnIndices[0]) {
    		//Log.i("[GameScreen]", "[updateRunning] tab Y == " + String.valueOf(anchorFirstTab.GetNewY()));
    		world.GetRules().Scroll(true, deltaTime * 500);	Settings.columnIndices[2] = -2;	// moving left
    		if (anchorFirstTab.GetY() > leftAnchorY + anchorHeight * Settings.columnIndices[0]) {
    			world.GetRules().ScrollImmed(true, leftAnchorY + anchorHeight * Settings.columnIndices[0]);
    		}
    	} else if (anchorFirstTab.GetY() > leftAnchorY + anchorHeight * Settings.columnIndices[0]) {
    		//Log.i("[GameScreen]", "[updateRunning] 2tab Y == " + String.valueOf(anchorFirstTab.GetNewY()));
    		world.GetRules().Scroll(true, -deltaTime * 500);	Settings.columnIndices[2] = 2;	// moving right
    		if (anchorFirstTab.GetY() < leftAnchorY + anchorHeight * Settings.columnIndices[0]) {
    			world.GetRules().ScrollImmed(true, leftAnchorY + anchorHeight * Settings.columnIndices[0]);
    		}
    	}
    	Settings.columnIndices[2] = 0;	// stop

    	if (World.MODE_NORMAL == world.mViewMode && Settings.anchor2anchor[3] >= 0.2f && Settings.anchor2anchor[4] == 1) {
    		// Checks if autoplay can be on
    		world.GetRules().EventAlert(Rules.EVENT_SMART_MOVE);
    	}
    	
        List<TouchEvent> touchEvents = game.getInput().getTouchEvents();
        int len = touchEvents.size();
        
        for (int i = 0; i < len; i++) {
            TouchEvent event = touchEvents.get(i);
            if(event.type == TouchEvent.TOUCH_DOWN) {
            	touchPoint.set(event.x, event.y);
            	touchDownPoint.set(event.x, event.y);
            	touchDownPoint_delta.set(event.x, event.y);	// to make delta distance every time
            	guiCam.touchToWorld(touchPoint);
            	guiCam.touchToWorld(touchDownPoint);
            	guiCam.touchToWorld(touchDownPoint_delta);
            	
            	if (World.MODE_NORMAL == world.mViewMode) {
            		int cardAnchors = world.GetCardAnchors().length;
	                for (int cardAnchorIdx = 0; cardAnchorIdx < cardAnchors; ++cardAnchorIdx) {
	                	// Hidden anchors disabled
//	                	if (cardAnchorIdx == 0 && Settings.columnIndices[1] > 0)	continue;
//	                	if (cardAnchorIdx == 1 && Settings.columnIndices[1] > 1)	continue;
//	                	if (cardAnchorIdx == 1 && Settings.columnIndices[0])	continue;
	                	CardAnchor cardAnchor = world.GetCardAnchors()[cardAnchorIdx];
	                	Card card = null;
	                	if (isTouchedAreaAllowed(touchPoint.x, touchPoint.y)) {
	                		card = cardAnchor.GrabCard(touchPoint.x, touchPoint.y);
	                	}
	                    if (card != null) {
	                    	if (touchPoint.y < card.GetY() + Card.WIDTH / 4) {
	                    		boolean lastIgnore = world.GetRules().GetIgnoreEvents();
	                    		world.GetRules().SetIgnoreEvents(true);
	                    		cardAnchor.AddCard(card);
	                    		world.GetRules().SetIgnoreEvents(lastIgnore);
	                    		card = cardAnchor.PopCard();
	                    	}
	                    	world.GetMoveCards().SetAnchor(cardAnchor, cardAnchorIdx);
	                    	world.GetMoveCards().AddCard(card);
	                    	world.ChangeViewMode(World.MODE_MOVE_CARD);
	                    	break;
	                    }
	                }
            	}
                else if (World.MODE_CARD_SELECT == world.mViewMode) {
                	world.GetSelectCards().Tap(touchPoint.x, touchPoint.y);
                }
            } else if (event.type == TouchEvent.TOUCH_DRAGGED) {
            	touchPoint.set(event.x, event.y);
                guiCam.touchToWorld(touchPoint);

                if (isTouchedAreaAllowed(touchPoint.x, touchPoint.y)) {
	            	if (World.MODE_NORMAL == world.mViewMode) {
	                	int cardAnchors = world.GetCardAnchors().length;
	                	// if the moving distance is greater than 30 pixels, the mode is MODE_MOVE_CARD
	                    if (Math.abs(touchDownPoint.x - touchPoint.x) > 30 || Math.abs(touchDownPoint.y - touchPoint.y) > 30) {
	                    	for (int cardAnchorIdx = 0; cardAnchorIdx < cardAnchors; ++cardAnchorIdx) {
	                    		CardAnchor cardAnchor = world.GetCardAnchors()[cardAnchorIdx];
	                    		if (cardAnchor.CanMoveStack(touchDownPoint.x, touchDownPoint.y)) {
	                    			//Log.i("[GameScreen]", "[updateRunning] InitFromAnchor: " + String.valueOf(cardAnchorIdx));
	                    			world.GetMoveCards().InitFromAnchor(cardAnchor, cardAnchorIdx, touchPoint.x, touchPoint.y);
	                    			world.ChangeViewMode(World.MODE_MOVE_CARD);
	                    			break;
	                    			//return;
	                    		}
	                    	}
	                    }
	                } else if (World.MODE_MOVE_CARD == world.mViewMode) {
	                	world.GetMoveCards().SetPosition(touchPoint.x, touchPoint.y);
	                } else if (World.MODE_CARD_SELECT == world.mViewMode) {
	                	SelectCard selectCard = world.GetSelectCards();
	                	int cardAnchorIdx = world.GetSelectCards().GetCardAnchorIdx();
	                    if (selectCard.IsOnCard() && Math.abs(touchDownPoint.y - touchPoint.y) > 30) {
	                    	world.GetMoveCards().InitFromSelectCard(selectCard, cardAnchorIdx, touchPoint.x, touchPoint.y);
	                    	world.ChangeViewMode(World.MODE_MOVE_CARD);
	                    } else {
	                    	selectCard.Scroll(touchPoint.x - touchDownPoint_delta.x);
	                    	touchDownPoint_delta.set(event.x, event.y);
	                        guiCam.touchToWorld(touchDownPoint_delta);
	                    	if (!selectCard.IsOnCard()) {
	                    		selectCard.Tap(touchPoint.x, touchPoint.y);
	                    	}
	                    }
	                }
                }
            }
            if (event.type == TouchEvent.TOUCH_UP) {
            	touchPoint.set(event.x, event.y);
                guiCam.touchToWorld(touchPoint);
                
                // Column scrolls
                if (OverlapTester.pointInRectangle(rect_colscrollLeftTab, touchPoint) && 0 < Settings.columnIndices[0]) {
                	--Settings.columnIndices[0];
            	} else if (OverlapTester.pointInRectangle(rect_colscrollLeftFound, touchPoint) && 0 < Settings.columnIndices[1]) {
            		--Settings.columnIndices[1];
            	} else if (OverlapTester.pointInRectangle(rect_colscrollRightTab, touchPoint)
            			&& Settings.columnIndices[0] + Settings.columnNum < Settings.anchorNum[0]) {
            		++Settings.columnIndices[0];
            	} else if (OverlapTester.pointInRectangle(rect_colscrollRightFound, touchPoint)
            			&& Settings.columnIndices[1] + Settings.columnNum < Settings.anchorNum[1]) {
            		++Settings.columnIndices[1];
            	}

            	if (World.MODE_NORMAL == world.mViewMode) {
                	int cardAnchors = world.GetCardAnchors().length;
                	for (int cardAnchorIdx = 0; cardAnchorIdx < cardAnchors; ++cardAnchorIdx) {
                		CardAnchor cardAnchor = world.GetCardAnchors()[cardAnchorIdx];
                		if (isTouchedAreaAllowed(touchPoint.x, touchPoint.y)) {
	                		if (cardAnchor.ExpandStack(touchPoint.x, touchPoint.y)) {
	//                			Log.i("[GameScreen]", "[updateRunning] cardanchor " + String.valueOf(cardAnchorIdx) + ": expanded "
	//                					+ String.valueOf(touchPoint.x) + ", " + String.valueOf(touchPoint.y));
	                			world.GetSelectCards().InitFromAnchor(cardAnchor, cardAnchorIdx);
	                			world.ChangeViewMode(World.MODE_CARD_SELECT);
	                			//return true;
	                		} else if (cardAnchor.TapCard(touchPoint.x, touchPoint.y)) {
	                		//Log.i("[GameScreen]", "[updateRunning] cardanchor " + String.valueOf(cardAnchorIdx) + ": touched! "
	                				//+ String.valueOf(touchPoint.x) + ", " + String.valueOf(touchPoint.y));
	                			//return true;
	                		}
                		}
                	}
                } else if (World.MODE_MOVE_CARD == world.mViewMode) {
                	MoveCard moveCard = world.GetMoveCards();
                	boolean tmpCanDropCard = false;
	                for (int close = 0; close < 1; close++) {
	                    CardAnchor prevAnchor = moveCard.GetAnchor();
	                    boolean unhide = (prevAnchor.GetVisibleCount() == 0 && prevAnchor.GetCount() > 0);
	                    int count = moveCard.GetCount();
	                    //Log.i("[GameScreen]", "[updateRunning] movecard.GetCount() == " + String.valueOf(count));
	                    int cardAnchors = world.GetCardAnchors().length;

	                    for (int cardAnchorIdx = 0; cardAnchorIdx < cardAnchors; ++cardAnchorIdx) {
	                    	CardAnchor cardAnchor = world.GetCardAnchors()[cardAnchorIdx];
	                    	if (cardAnchor != prevAnchor) {
	                    		if (cardAnchor.CanDropCard(moveCard, close)) {
	                    			world.GetRules().MovePush(prevAnchor.GetNumber(), cardAnchorIdx, count, false, unhide);
	                    			//world.GetHistory().push(new Move(prevAnchor.GetNumber(), cardAnchorIdx, count, false, unhide));
	                    			cardAnchor.AddMoveCard(moveCard, cardAnchorIdx);
	                    			if (World.MODE_MOVE_CARD == world.mViewMode) {
	                    				world.ChangeViewMode(World.MODE_NORMAL);
	                    			}
	                    			tmpCanDropCard = true;
	                    			break;
	                    			//return;
	                    		}
	                    	}
	                    }
	                }
	                if (!tmpCanDropCard) {
		                if (!moveCard.HasMoved()) {
		                    CardAnchor anchor = moveCard.GetAnchor();
		                    moveCard.Release();
		                    if (anchor.ExpandStack(touchPoint.x, touchPoint.y) && isTouchedAreaAllowed(touchPoint.x, touchPoint.y)) {
		                    	moveCard.Release();
		                    	world.GetSelectCards().InitFromAnchor(anchor, moveCard.GetAnchorIdx(false));
		                    	world.ChangeViewMode(World.MODE_CARD_SELECT);
		                    } else {
		                    	world.ChangeViewMode(World.MODE_NORMAL);
		                    }
		                } else if (/*mSpeed.IsFast() &&*/ moveCard.GetCount() == 1) {
		                	//Log.i("[GameScreen]", "[updateRunning] !tmpCanDropCard && moveCard == 1");
		                	world.GetRules().Fling(moveCard);
		                	world.ChangeViewMode(World.MODE_NORMAL);
		                } else {
		                  	moveCard.Release();
		                  	world.ChangeViewMode(World.MODE_NORMAL);
		                }
	                }
                }
                else if (World.MODE_CARD_SELECT == world.mViewMode) {
                	if (!world.GetSelectCards().IsOnCard()/* && !mHasMoved*/) {
                        world.GetSelectCards().Release();
                        world.ChangeViewMode(World.MODE_NORMAL);
                        //return;
                	}
                }
                
                // Buttons on status bar
                if (OverlapTester.pointInRectangle(rect_btnAutoplay, touchPoint)) {
                	Settings.autoplayFlag = !Settings.autoplayFlag;
            	} else if (OverlapTester.pointInRectangle(rect_btnUndo, touchPoint)) {
                	if (!world.GetHistory().empty()) {	world.Undo();	}
            	} else if (OverlapTester.pointInRectangle(rect_btnRedo, touchPoint)) {
                	if (!world.GetUndoHistory().empty()) {	world.Redo();	}
            	} else if (OverlapTester.pointInRectangle(rect_btnZIn, touchPoint)) {
            		if (World.MODE_CARD_SELECT == world.mViewMode) {	world.mViewMode = World.MODE_NORMAL;	}
            		if (Settings.columnNum > Settings.MIN_COLUMN_NUM) {	Settings.columnNum--;	}
            		else	Settings.columnNum = Settings.MIN_COLUMN_NUM;
            		Card.Resize();
            		world.GetRules().Resize(Settings.WORLD_WIDTH, Settings.WORLD_HEIGHT);
            	} else if (OverlapTester.pointInRectangle(rect_btnZOut, touchPoint)) {
            		if (World.MODE_CARD_SELECT == world.mViewMode) {	world.mViewMode = World.MODE_NORMAL;	}
            		if (Settings.columnNum < Settings.MAX_COLUMN_NUM) {	Settings.columnNum++;	}
            		else	Settings.columnNum = Settings.MAX_COLUMN_NUM;
            		Card.Resize();
            		world.GetRules().Resize(Settings.WORLD_WIDTH, Settings.WORLD_HEIGHT);
            	}
            }
        }
        
        //world.update(deltaTime, game.getInput().getAccelY(), game.getInput().getAccelX(), deltaPos);
        //world.update(deltaTime, -game.getInput().getAccelX(), game.getInput().getAccelY(), deltaPos);
        if (world.score != lastScore) {
            lastScore = world.score;
            scoreString = "" + lastScore;
        }
        if (world.mViewMode == World.MODE_WIN) {
            state = GAME_LEVEL_END;        
        }

        //Log.i("[GameScreen]", "[updateRunning] before HandleEvents");
        world.GetRules().HandleEvents();
        
		// Animating
		Settings.anchor2anchor[3] += deltaTime;
		if (Settings.anchor2anchor[3] >= 0.2f)	Settings.anchor2anchor[3] = 0.2f;	// animation done
    }
    
    private boolean isTouchedAreaAllowed(float x, float y) {
    	return (Settings.BTN_SCROLL_WIDTH < y) && (y < Settings.WORLD_HEIGHT - Settings.BTN_SCROLL_WIDTH) && (x > 100.0f); 
    }

    private void updatePaused() {
        List<TouchEvent> touchEvents = game.getInput().getTouchEvents();
        int len = touchEvents.size();
        for (int i = 0; i < len; i++) {
            TouchEvent event = touchEvents.get(i);
            if(event.type != TouchEvent.TOUCH_UP)
                continue;
            
            touchPoint.set(event.x, event.y);
            guiCam.touchToWorld(touchPoint);
        }
    }

    private void updateLevelEnd() {
        List<TouchEvent> touchEvents = game.getInput().getTouchEvents();
        int len = touchEvents.size();
        for(int i = 0; i < len; i++) {                   
            TouchEvent event = touchEvents.get(i);
            if(event.type != TouchEvent.TOUCH_UP)
                continue;

//            if(OverlapTester.pointInRectangle(pauseBounds, touchPoint)) {
//        		//Assets.playSound(Assets.clickSound);
//            	//Settings.enabledFunc[3] = false;
//                Settings.scrGame2Main = true;
//                game.setScreen(new MainMenuScreen(game));
//        		return;
//        	}
        }
    }

    private void updateGameOver() {
        List<TouchEvent> touchEvents = game.getInput().getTouchEvents();
        int len = touchEvents.size();
        for(int i = 0; i < len; i++) {                   
            TouchEvent event = touchEvents.get(i);
            if(event.type != TouchEvent.TOUCH_UP)
                continue;
        }
    }

    @Override
    public void present(float deltaTime) {
        GL10 gl = glGraphics.getGL();
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
        gl.glEnable(GL10.GL_TEXTURE_2D);
        
        renderer.render(deltaTime);
        
        guiCam.setViewportAndMatrices();
        gl.glEnable(GL10.GL_BLEND);
        gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
        //batcher.beginBatch(Assets.items);
        switch(state) {
        case GAME_EXECUTE:	break;
        case GAME_SETTINGS:	presentSettings();	break;
        case GAME_READY:break;
        case GAME_RUNNING:
            presentRunning();
            break;
        case GAME_LEVEL_END:
            presentLevelEnd();
            break;
        case GAME_OVER:
            presentGameOver();
            break;
        }
        //batcher.endBatch();
        gl.glDisable(GL10.GL_BLEND);
    }
    
    private void presentSettings() {
    	batcher.beginBatch(Assets.tex_bg);
        batcher.drawSprite(Settings.WORLD_WIDTH / 2, Settings.WORLD_HEIGHT / 2,
        		(300 + 20) * 3, (160 + 20) * 3, -90, Assets.bg_game_settings);
        batcher.endBatch();
        batcher.beginBatch(Assets.tex_gameset);
        // Title
        batcher.drawSprite(gameset.getCoordsTitle().x, gameset.getCoordsTitle().y, 500, 80, -90, Assets.gameset_title);
        // Menus
        batcher.drawSprite(gameset.getCoordsMenuSuits().x, gameset.getCoordsMenuSuits().y, 200, 60, -90, Assets.gameset_menu_suits);
        batcher.drawSprite(gameset.getCoordsMenuDecks().x, gameset.getCoordsMenuDecks().y, 200, 60, -90, Assets.gameset_menu_decks);
        batcher.drawSprite(gameset.getCoordsMenuRanks().x, gameset.getCoordsMenuRanks().y, 200, 60, -90, Assets.gameset_menu_ranks);
        batcher.drawSprite(gameset.getCoordsMenuDeal().x, gameset.getCoordsMenuDeal().y, 200, 60, -90, Assets.gameset_menu_deal);
        // Buttons (OK, CANCEL)
        batcher.drawSprite(gameset.getCoordsBtnOk().x, gameset.getCoordsBtnOk().y, 300, 90, -90, Assets.gameset_btn_ok);
        batcher.drawSprite(gameset.getCoordsBtnCancel().x, gameset.getCoordsBtnCancel().y, 300, 90, -90, Assets.gameset_btn_cancel);
        TextureRegion tmpTexRegion;
        // 1st row (SUITS)
        for (int i = 0; i <= 2; ++i) {
        	tmpTexRegion = (Settings.gameSettings_max[0] < i) ? Assets.gameset_disabled : ((lastGameSettings[0] == i) ? Assets.gameset_check_yes : Assets.gameset_check_no); 
        	batcher.drawSprite(gameset.getCoordsIcons(0, i).x, gameset.getCoordsIcons(0, i).y, 60, 60, -90, tmpTexRegion);
        }
        batcher.drawSprite(gameset.getCoordsDigits(0, 0, false).x, gameset.getCoordsDigits(0, 0, false).y, 30, 60, -90, Settings.gameSettings_max[0] < 0 ? Assets.gameset_dis_4 : Assets.gameset_en_4);
        batcher.drawSprite(gameset.getCoordsDigits(0, 1, false).x, gameset.getCoordsDigits(0, 1, false).y, 30, 60, -90, Settings.gameSettings_max[0] < 1 ? Assets.gameset_dis_6 : Assets.gameset_en_6);
        batcher.drawSprite(gameset.getCoordsDigits(0, 2, false).x, gameset.getCoordsDigits(0, 2, false).y, 30, 60, -90, Settings.gameSettings_max[0] < 2 ? Assets.gameset_dis_8 : Assets.gameset_en_8);
        //batcher.drawSprite(gameset.getCoordsDigits(0, 0, false).x, gameset.getCoordsDigits(0, 0, false).y, 30, 60, -90, Assets.gameset_lock_4);
        //batcher.drawSprite(gameset.getCoordsDigits(0, 1, false).x, gameset.getCoordsDigits(0, 1, false).y, 30, 60, -90, Assets.gameset_lock_6);
        //batcher.drawSprite(gameset.getCoordsDigits(0, 2, false).x, gameset.getCoordsDigits(0, 2, false).y, 30, 60, -90, Assets.gameset_lock_8);
        // 2nd row (DECKS)
        for (int i = 0; i <= 3; ++i) {
        	tmpTexRegion = (Settings.gameSettings_max[1] < i) ? Assets.gameset_disabled : ((lastGameSettings[1] == i) ? Assets.gameset_check_yes : Assets.gameset_check_no);
        	batcher.drawSprite(gameset.getCoordsIcons(1, i).x, gameset.getCoordsIcons(1, i).y, 60, 60, -90, tmpTexRegion);
        }
        batcher.drawSprite(gameset.getCoordsDigits(1, 0, false).x, gameset.getCoordsDigits(1, 0, false).y, 30, 60, -90, Settings.gameSettings_max[1] < 0 ? Assets.gameset_dis_1 : Assets.gameset_en_1);
        batcher.drawSprite(gameset.getCoordsDigits(1, 1, false).x, gameset.getCoordsDigits(1, 1, false).y, 30, 60, -90, Settings.gameSettings_max[1] < 1 ? Assets.gameset_dis_2 : Assets.gameset_en_2);
        batcher.drawSprite(gameset.getCoordsDigits(1, 2, false).x, gameset.getCoordsDigits(1, 2, false).y, 30, 60, -90, Settings.gameSettings_max[1] < 2 ? Assets.gameset_dis_3 : Assets.gameset_en_3);
        batcher.drawSprite(gameset.getCoordsDigits(1, 3, false).x, gameset.getCoordsDigits(1, 3, false).y, 30, 60, -90, Settings.gameSettings_max[1] < 3 ? Assets.gameset_dis_4 : Assets.gameset_en_4);
//        batcher.drawSprite(gameset.getCoordsDigits(1, 0, false).x, gameset.getCoordsDigits(1, 0, false).y, 30, 60, -90, Assets.gameset_lock_1);
//        batcher.drawSprite(gameset.getCoordsDigits(1, 1, false).x, gameset.getCoordsDigits(1, 1, false).y, 30, 60, -90, Assets.gameset_lock_2);
//        batcher.drawSprite(gameset.getCoordsDigits(1, 2, false).x, gameset.getCoordsDigits(1, 2, false).y, 30, 60, -90, Assets.gameset_lock_3);
//        batcher.drawSprite(gameset.getCoordsDigits(1, 3, false).x, gameset.getCoordsDigits(1, 3, false).y, 30, 60, -90, Assets.gameset_lock_4);
        // 3rd row (RANKS)
        for (int i = 0; i <= 2; ++i) {
        	tmpTexRegion = (Settings.gameSettings_max[2] < i) ? Assets.gameset_disabled : ((lastGameSettings[2] == i) ? Assets.gameset_check_yes : Assets.gameset_check_no); 
        	batcher.drawSprite(gameset.getCoordsIcons(2, i).x, gameset.getCoordsIcons(2, i).y, 60, 60, -90, tmpTexRegion);
        }
        batcher.drawSprite(gameset.getCoordsDigits(2, 0, true).x, gameset.getCoordsDigits(2, 0, true).y, 30, 60, -90, Settings.gameSettings_max[2] < 0 ? Assets.gameset_dis_1 : Assets.gameset_en_1);
        batcher.drawSprite(gameset.getCoordsDigits(2, 0, false).x, gameset.getCoordsDigits(2, 0, false).y, 30, 60, -90, Settings.gameSettings_max[2] < 0 ? Assets.gameset_dis_3 : Assets.gameset_en_3);
        batcher.drawSprite(gameset.getCoordsDigits(2, 1, true).x, gameset.getCoordsDigits(2, 1, true).y, 30, 60, -90, Settings.gameSettings_max[2] < 1 ? Assets.gameset_dis_1 : Assets.gameset_en_1);
        batcher.drawSprite(gameset.getCoordsDigits(2, 1, false).x, gameset.getCoordsDigits(2, 1, false).y, 30, 60, -90, Settings.gameSettings_max[2] < 1 ? Assets.gameset_dis_8 : Assets.gameset_en_8);
        batcher.drawSprite(gameset.getCoordsDigits(2, 2, true).x, gameset.getCoordsDigits(2, 2, true).y, 30, 60, -90, Settings.gameSettings_max[2] < 2 ? Assets.gameset_dis_2 : Assets.gameset_en_2);
        batcher.drawSprite(gameset.getCoordsDigits(2, 2, false).x, gameset.getCoordsDigits(2, 2, false).y, 30, 60, -90, Settings.gameSettings_max[2] < 2 ? Assets.gameset_dis_3 : Assets.gameset_en_3);
//        batcher.drawSprite(gameset.getCoordsDigits(2, 0, true).x, gameset.getCoordsDigits(2, 0, true).y, 30, 60, -90, Assets.gameset_lock_1);
//        batcher.drawSprite(gameset.getCoordsDigits(2, 0, false).x, gameset.getCoordsDigits(2, 0, false).y, 30, 60, -90, Assets.gameset_lock_3);
//        batcher.drawSprite(gameset.getCoordsDigits(2, 1, true).x, gameset.getCoordsDigits(2, 1, true).y, 30, 60, -90, Assets.gameset_lock_1);
//        batcher.drawSprite(gameset.getCoordsDigits(2, 1, false).x, gameset.getCoordsDigits(2, 1, false).y, 30, 60, -90, Assets.gameset_lock_8);
//        batcher.drawSprite(gameset.getCoordsDigits(2, 2, true).x, gameset.getCoordsDigits(2, 2, true).y, 30, 60, -90, Assets.gameset_lock_2);
//        batcher.drawSprite(gameset.getCoordsDigits(2, 2, false).x, gameset.getCoordsDigits(2, 2, false).y, 30, 60, -90, Assets.gameset_lock_3);
        // 4th row (DEAL)
        for (int i = 0; i <= 1; ++i) {
        	tmpTexRegion = (Settings.gameSettings_max[3] < i) ? Assets.gameset_disabled : ((lastGameSettings[3] == i) ? Assets.gameset_check_yes : Assets.gameset_check_no); 
        	batcher.drawSprite(gameset.getCoordsIcons(3, i).x, gameset.getCoordsIcons(3, i).y, 60, 60, -90, tmpTexRegion);
        }
        batcher.drawSprite(gameset.getCoordsDigits(3, 0, false).x, gameset.getCoordsDigits(3, 0, false).y, 30, 60, -90, Settings.gameSettings_max[3] < 0 ? Assets.gameset_dis_1 : Assets.gameset_en_1);
        batcher.drawSprite(gameset.getCoordsDigits(3, 1, false).x, gameset.getCoordsDigits(3, 1, false).y, 30, 60, -90, Settings.gameSettings_max[3] < 1 ? Assets.gameset_dis_3 : Assets.gameset_en_3);
//        batcher.drawSprite(gameset.getCoordsDigits(3, 0, false).x, gameset.getCoordsDigits(3, 0, false).y, 30, 60, -90, Assets.gameset_lock_1);
//        batcher.drawSprite(gameset.getCoordsDigits(3, 1, false).x, gameset.getCoordsDigits(3, 1, false).y, 30, 60, -90, Assets.gameset_lock_3);
        batcher.endBatch();
    }

    private void presentRunning() {
    	String strScore = "";
    	batcher.beginBatch(Assets.tex_bg);
    	// Column scroll for tableaus
    	TextureRegion scrollLeft = (0 < Settings.columnIndices[0]) ? Assets.bg_colscroll_left : Assets.bg_colscroll_left_dis;
    	if (2 == Settings.columnIndices[2])	scrollLeft = Assets.bg_colscroll_moving;
    	TextureRegion scrollLeftArrow = (0 < Settings.columnIndices[0]) ? Assets.bg_colscroll_left_arrow : Assets.bg_colscroll_left_dis_arrow;
    	TextureRegion scrollRight = (Settings.columnIndices[0] + Settings.columnNum < Settings.anchorNum[0])
    			? Assets.bg_colscroll_right : Assets.bg_colscroll_right_dis;
    	if (-2 == Settings.columnIndices[2])	scrollRight = Assets.bg_colscroll_moving;
    	TextureRegion scrollRightArrow = (Settings.columnIndices[0] + Settings.columnNum < Settings.anchorNum[0])
    			? Assets.bg_colscroll_right_arrow : Assets.bg_colscroll_right_dis_arrow;
    	float tmpScrollX = (Settings.WORLD_WIDTH - Card.WIDTH - 140) / 2 + 100, tmpScrollWidth = Settings.WORLD_WIDTH - Card.WIDTH - 100;
    	batcher.drawSprite(tmpScrollX, Settings.WORLD_HEIGHT - 20, 40, tmpScrollWidth, -90, scrollLeft);
    	batcher.drawSprite(tmpScrollX, Settings.WORLD_HEIGHT - 20, 40, 40, -90, scrollLeftArrow);
    	batcher.drawSprite(tmpScrollX, 20, 40, tmpScrollWidth, -90, scrollRight);
    	batcher.drawSprite(tmpScrollX, 20, 40, 40, -90, scrollRightArrow);
    	// Column scroll for foundations, stock, and waste
    	scrollLeft = (0 < Settings.columnIndices[1]) ? Assets.bg_colscroll_left : Assets.bg_colscroll_left_dis;
    	if (1 == Settings.columnIndices[2])	scrollRight = Assets.bg_colscroll_moving;
    	scrollLeftArrow = (0 < Settings.columnIndices[1]) ? Assets.bg_colscroll_left_arrow : Assets.bg_colscroll_left_dis_arrow;
    	scrollRight = (Settings.columnIndices[1] + Settings.columnNum < Settings.anchorNum[1])
    			? Assets.bg_colscroll_right : Assets.bg_colscroll_right_dis;
    	if (-1 == Settings.columnIndices[2])	scrollLeft = Assets.bg_colscroll_moving;
    	scrollRightArrow = (Settings.columnIndices[1] + Settings.columnNum < Settings.anchorNum[1])
    			? Assets.bg_colscroll_right_arrow : Assets.bg_colscroll_right_dis_arrow;
    	tmpScrollX = Settings.WORLD_WIDTH - (10 + Card.WIDTH) / 2;	tmpScrollWidth = Card.WIDTH + 10;
    	batcher.drawSprite(tmpScrollX, Settings.WORLD_HEIGHT - 20, 40, tmpScrollWidth, -90, scrollLeft);
    	batcher.drawSprite(tmpScrollX, Settings.WORLD_HEIGHT - 20, 40, 40, -90, scrollLeftArrow);
    	batcher.drawSprite(tmpScrollX, 20, 40, tmpScrollWidth, -90, scrollRight);
    	batcher.drawSprite(tmpScrollX, 20, 40, 40, -90, scrollRightArrow);
    	batcher.endBatch();

    	batcher.beginBatch(Assets.tex_statusbar);
    	batcher.drawSprite(50, Settings.WORLD_HEIGHT / 2, Settings.WORLD_HEIGHT, 100, -90, Assets.sbar_statusbar);
    	if (Settings.columnNum <= Settings.MIN_COLUMN_NUM) {
    		Settings.columnNum = Settings.MIN_COLUMN_NUM;
    		batcher.drawSprite(40, Settings.WORLD_HEIGHT - 105 * 1 / 2, 105, 60, -90, Assets.sbar_status_zin_dis);
    		batcher.drawSprite(40, Settings.WORLD_HEIGHT - 105 * 3 / 2, 105, 60, -90, Assets.sbar_status_zout);
    	} else if (Settings.columnNum >= Settings.MAX_COLUMN_NUM) {
    		Settings.columnNum = Settings.MAX_COLUMN_NUM;
    		batcher.drawSprite(40, Settings.WORLD_HEIGHT - 105 * 1 / 2, 105, 60, -90, Assets.sbar_status_zin);
    		batcher.drawSprite(40, Settings.WORLD_HEIGHT - 105 * 3 / 2, 105, 60, -90, Assets.sbar_status_zout_dis);
    	} else {
    		batcher.drawSprite(40, Settings.WORLD_HEIGHT - 105 * 1 / 2, 105, 60, -90, Assets.sbar_status_zin);
    		batcher.drawSprite(40, Settings.WORLD_HEIGHT - 105 * 3 / 2, 105, 60, -90, Assets.sbar_status_zout);
    	}
    	if (Settings.autoplayFlag) {
    		batcher.drawSprite(40, 105 * 5 / 2, 105, 60, -90, Assets.sbar_status_autoon);
    	} else {
    		batcher.drawSprite(40, 105 * 5 / 2, 105, 60, -90, Assets.sbar_status_autooff);
    	}
    	if (!world.GetHistory().empty()) {
    		batcher.drawSprite(40, 105 * 3 / 2, 105, 60, -90, Assets.sbar_status_undo);
    	} else {
    		batcher.drawSprite(40, 105 * 3 / 2, 105, 60, -90, Assets.sbar_status_undo_dis);
    	}
    	if (!world.GetUndoHistory().empty()) {
    		batcher.drawSprite(40, 105 * 1 / 2, 105, 60, -90, Assets.sbar_status_redo);
    	} else {
    		batcher.drawSprite(40, 105 * 1 / 2, 105, 60, -90, Assets.sbar_status_redo_dis);
    	}
    	batcher.endBatch();
//    	switch (Settings.orient) {
//    	default:
//    		strScore = String.format("Time:%05.1f Deaths:%03d Rot:%03d"
//    				, Settings.curScores.timeElapsed, Settings.curScores.deaths, tmpRot);
//    		Assets.font.drawTextLandscape(batcher, strScore, 16, 16, false, false);
//    		break;
//    	}
    	
    	//if (Settings.enabledFunc[1])	presentTutorial();
    }

//    private void presentPaused() {        
//        //batcher.drawSprite(160, 240, 192, 96, Assets.pauseMenu);
//        Assets.font.drawText(batcher, scoreString, 16, 480-20);
//    }

    private void presentLevelEnd() {
        String topText = "LEVEL COMPLETED!";
        float topWidth = Assets.font.glyphWidth * topText.length();
        //Assets.font.drawTextLandscape(batcher, topText, 160 - topWidth / 2, 480 - 40, false, true);
    }

    private void presentGameOver() {
        //batcher.drawSprite(160, 240, 160, 96, Assets.gameOver);        
        float scoreWidth = Assets.font.glyphWidth * scoreString.length();
        Assets.font.drawText(batcher, scoreString, 160 - scoreWidth / 2, 480-20);
    }

    @Override
    public void pause() {
    }

    @Override
    public void resume() {
    }

    @Override
    public void dispose() {       
    }
}
